/*
 * FunctionCallExpressionDescription.java
 * 
 * last update: 01.02.2010 by Florea Mihai
 * 
 * author:	Alec(panovici@elcom.pub.ro)
 * 			Florea Mihai(florea.mihai@gmail.com)
 * 
 * Obs: Am adaugat <Object> si @SuppressWarnings("serial") acolo unde era cazul.
 */


package engine;

//import middle.*;
import java.util.*;

/**
 * The description of a funcction call expression. 
 * It creates the required registers for the actual parameters (whose types are known only at instantiation time).
 */

@SuppressWarnings("serial")
class FunctionCallExpressionDescription implements ExpressionDescription{

	/**
	 * Contains the expressionDescriptions for the actual parameters.
	 */
	
	Vector<Object> actualParamsDescs;

	/**
	 * The invoked func name.
	 */
	FQNDescription funcName;


	FunctionCallExpressionDescription(FQNDescription funcName,
			Vector<Object> actualParamsDescs){
		this.actualParamsDescs = actualParamsDescs;
		this.funcName = funcName;
	}

	/**
	 * Creates the placeholders for the actuel parameters
	 * transfer and the DefaultInstruction for the func invocation.
	 */
	public Expression instantiate(NameSpace ns)throws ParseException{
		Vector<Object> actualParams = new Vector<Object>();
		Vector<Object> paramInstances;

		for(Enumeration<Object> e = actualParamsDescs.elements() ; e.hasMoreElements() ; ){
			//link the expressions to the caller's NameSpace (ns)
			try{
				actualParams.addElement(((ExpressionDescription)
						e.nextElement()).instantiate(ns));
			}catch(ParseException ex){
				xConsole.dumpStack(ex);
				throw new ParseException(super.toString() + " error:" + ex);
			}
		}

		NameSpace funcSpace;
		try {
			funcSpace = (NameSpace)ns.resolveName(funcName.instantiate(ns));
			//just checking that this name refers the correct NameSpace
			if(funcSpace == null)
				throw new ParseException(super.toString() +
						" error:symbol \"" +
						funcName + "\" not found");
			if(! (funcSpace.desc instanceof FunctionDescription))
				throw new ClassCastException();
		} catch(ClassCastException ex) {
			throw new ParseException(super.toString() +
					" error:" + funcName + " is not a function");
		}

		FunctionDescription funcDescription = (FunctionDescription) funcSpace.desc;
		try { 
			paramInstances = funcDescription.createParams(funcSpace, actualParams);
		} catch(ParseException ex) {
			xConsole.dumpStack(ex);
			throw new ParseException(toString() + " error:" + ex);
		}
		xConsole.debug("func description is: " + funcDescription);
		try {
			return new FunctionCallExpression(ns, this, funcDescription,
					actualParams, paramInstances,
					funcDescription.
					makeInstructionInstance(funcSpace));
		} catch(ParseException ex) {
			xConsole.dumpStack(ex);
			xConsole.cout(ex.toString());
			throw new ParseException("error inside called function");
		}
	}

	public String toString(){
		String res =  funcName + "(" ;
		for(Enumeration<Object> e = actualParamsDescs.elements() ; e.hasMoreElements() ;){
			res += ((ExpressionDescription)e.nextElement()).toString();
			if(e.hasMoreElements())res += ", ";
		}
		res += ");";
		return res;
	}
}




